﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.Helpers;
using com.IronOne.BoardPACWinAppBO.Agenda;
using com.IronOne.BoardPACWinAppBO.Comment;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Sync;
using com.IronOne.BoardPACWinAppService.Agenda;
using com.IronOne.BoardPACWinAppService.Comment;
using com.IronOne.BoardPACWinAppService.Meeting;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using RelayCommand = GalaSoft.MvvmLight.Command.RelayCommand;
using Windows.ApplicationModel.DataTransfer;

namespace com.IronOne.BoardPACWinApp.ViewModel
{
    public class AddCommentsViewModel : ViewModelBase
    {
        public delegate void ScrollToAddedCommentDel(string someparameter);

        public const string CommentsListPropertyName = "CommentsList";

        /// <summary>
        ///     The <see cref="Comment" /> property's name.
        /// </summary>
        public const string CommentPropertyName = "Comment";

        /// <summary>
        ///     The <see cref="CanExecute" /> property's name.
        /// </summary>
        public const string CanExecutePropertyName = "CanExecute";

        /// <summary>
        ///     The <see cref="MemberList" /> property's name.
        /// </summary>
        public const string MemberListPropertyName = "MemberList";

        /// <summary>
        ///     The <see cref="SelectedMemberList" /> property's name.
        /// </summary>
        public const string SelectedMemberListPropertyName = "SelectedMemberList";

        /// <summary>
        ///     The <see cref="CommentTypeHeading" /> property's name.
        /// </summary>
        public const string CommentTypeHeadingPropertyName = "CommentTypeHeading";

        public static int AgendaItemId = 0;
        public static int CommentType = 0; // 0 -> paperComment | 1 -> Meeting Comment
        private static string _commentTypeHeading;
        private RelayCommand<string> _addCommentsCommand;
        private bool _canExecute;
        private RelayCommand _clearCommand;
        private string _comment = string.Empty;
        private ObservableCollection<CommentModel> _commentsList;
        private RelayCommand<ObservableCollection<MemberModel>> _getSelectedMembersCommand;
        private RelayCommand<Object> _listViewItemClicked;
        private ObservableCollection<MemberModel> _memberList;
        private int _memberListFlyoutWidth;
        //private GalaSoft.MvvmLight.Command.RelayCommand _getSelectedMembersCommand;

        ///// <summary>
        ///// Gets the MyCommand.
        ///// </summary>
        //public GalaSoft.MvvmLight.Command.RelayCommand GetSelectedMembersCommand
        //{
        //    get
        //    {
        //        return _getSelectedMembersCommand
        //            ?? (_getSelectedMembersCommand = new GalaSoft.MvvmLight.Command.RelayCommand(
        //            () =>
        //            {
        //                if (!string.IsNullOrEmpty(Comment))
        //                {
        //                    List<int> userList = MemberList.Where(i => i.IsMemberSelected.Equals(true)).Select(m => m.MemberId).ToList();
        //                    AddComments(Comment, userList);
        //                }
        //                else
        //                {
        //                    _dialogService.ShowMessage("Please enter a comment");
        //                }

        //            }));
        //    }
        //}

        private RelayCommand<bool> _selectAllMembersCommand;
        private RelayCommand<bool> _selectAllMembersCommandTwo;
        private ObservableCollection<MemberModel> _selectedMemberList;
        public int RefId;
        private readonly IAgendaService _agendaService;
        private readonly ICommentService _commentService;
        private readonly IDialogService _dialogService;
        private readonly IMeetingService _meetingService;
        private const string ImgPath = "ms-appx:///Assets/Images/CommentsPage/";
        private DataTransferManager _dataTransferManager;
        string datetimeFormat = Utility.GetDateTimeFormat();

        public AddCommentsViewModel()
        {
            Messenger.Default.Register<NotificationMessage<MessageDataModel>>(this, HandleMessages);
            _commentService = new CommentService();
            _meetingService = new MeetingService();
            _agendaService = new AgendaService();
            _dialogService = new DialogService();

            CommentModel.EmailCommentOnClick -= OnEmailCommentClick;
            CommentModel.EmailCommentOnClick = null;
            CommentModel.EmailCommentOnClick += OnEmailCommentClick;

            GetMemberList();
            _memberListFlyoutWidth = (int)(Window.Current.Bounds.Width * 0.2);
            if (_memberListFlyoutWidth < Utility.GetFlyoutDefaultWidth())
                _memberListFlyoutWidth = Utility.GetFlyoutDefaultWidth();

            SelectedMemberList = new ObservableCollection<MemberModel>();
        }

        CommentModel _globalSelectedCommentItem = null;
        private void OnEmailCommentClick(object sender, EventArgs e)
        {
            _globalSelectedCommentItem = sender as CommentModel;

            _dataTransferManager = DataTransferManager.GetForCurrentView();
            _dataTransferManager.DataRequested += DataRequested;

            DataTransferManager.ShowShareUI();
        }

        private void DataRequested(DataTransferManager sender, DataRequestedEventArgs e)
        {
            try
            {
                var dataPackage = e.Request.Data;
                if (_globalSelectedCommentItem == null) return;
                var related = "";

                related = _globalSelectedCommentItem.CommentTypeName;
                dataPackage.Properties.Title = "Comment of " + related;

                dataPackage.Properties.Description = "Mail app is recommended for email";
                dataPackage.Properties.ApplicationName = "BoardPAC";
                dataPackage.SetHtmlFormat(
                    HtmlFormatHelper.CreateHtmlFormat(_globalSelectedCommentItem.Comment +
                                                      "<br/><br/><b>Related to:</b/><br/>" +
                                                      related +
                                                      "<br/><br/><b>Commented by:</b/><br/>" +
                                                      _globalSelectedCommentItem.CommentBy +
                                                      "<br/><br/><b>Date:</b/><br/>" +
                                                      _globalSelectedCommentItem.CommentDate.ToString(datetimeFormat)
                                                      ));
            }
            catch (Exception)
            {
            }
            finally
            {
                _dataTransferManager.DataRequested -= DataRequested;
            }
        }


        /// <summary>
        ///     Sets and gets the CommentsList property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public ObservableCollection<CommentModel> CommentsList
        {
            get { return _commentsList; }

            set
            {
                if (_commentsList == value)
                {
                    return;
                }

                _commentsList = value;
                RaisePropertyChanged(CommentsListPropertyName);
            }
        }

        public RelayCommand<string> AddCommentsCommand
        {
            get
            {
                return _addCommentsCommand
                       ?? (_addCommentsCommand = new RelayCommand<string>(
                           comment =>
                           {
                               if (!string.IsNullOrEmpty(Comment))
                               {
                                   //List<int> userList = new List<int> { Global.UserId };
                                   AddComments(comment, null);
                               }
                               else
                               {
                                   _dialogService.ShowMessage("Please enter a comment");
                               }
                           }));
            }
        }

        public int MemberListFlyoutWidth
        {
            get { return _memberListFlyoutWidth; }

            set
            {
                if (_memberListFlyoutWidth == value)
                {
                    return;
                }

                _memberListFlyoutWidth = value;
                RaisePropertyChanged("MemberListFlyoutWidth");
            }
        }

        /// <summary>
        ///     Sets and gets the Comment property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public string Comment
        {
            get { return _comment; }

            set
            {
                if (_comment == value)
                {
                    return;
                }

                _comment = value;
                CanExecute = !string.IsNullOrEmpty(_comment);
                RaisePropertyChanged(CommentPropertyName);
            }
        }

        /// <summary>
        ///     Sets and gets the CanExecute property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public bool CanExecute //Enable comment share button and private button
        {
            get { return _canExecute; }

            set
            {
                if (_canExecute == value)
                {
                    return;
                }

                _canExecute = value;
                RaisePropertyChanged(CanExecutePropertyName);
            }
        }

        /// <summary>
        ///     Sets and gets the MemberList property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public ObservableCollection<MemberModel> MemberList
        {
            get { return _memberList; }

            set
            {
                if (_memberList == value)
                {
                    return;
                }

                _memberList = value;
                RaisePropertyChanged(MemberListPropertyName);
            }
        }

        /// <summary>
        ///     Sets and gets the SelectedMemberList property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public ObservableCollection<MemberModel> SelectedMemberList
        {
            get { return _selectedMemberList; }

            set
            {
                if (_selectedMemberList == value)
                {
                    return;
                }

                _selectedMemberList = value;
                RaisePropertyChanged(SelectedMemberListPropertyName);
            }
        }

        /// <summary>
        ///     Gets the MyCommand.
        /// </summary>
        public RelayCommand<Object> ListViewItemClicked
        {
            get
            {
                return _listViewItemClicked
                       ?? (_listViewItemClicked = new RelayCommand<Object>(
                           item => { }));
            }
        }

        /// <summary>
        ///     Gets the MyCommand.
        /// </summary>
        public RelayCommand<ObservableCollection<MemberModel>> GetSelectedMembersCommand
        {
            get
            {
                return _getSelectedMembersCommand
                       ?? (_getSelectedMembersCommand = new RelayCommand<ObservableCollection<MemberModel>>(
                           items =>
                           {
                               if (!string.IsNullOrEmpty(Comment))
                               {
                                   var userList =
                                       items.Where(i => i.IsMemberSelected.Equals(true))
                                           .Select(m => m.MemberId)
                                           .ToList();
                                   AddComments(Comment, userList);
                               }
                               else
                               {
                                   _dialogService.ShowMessage("Please enter a comment");
                               }
                           }));
            }
        }

        /// <summary>
        ///     Gets the MyCommand.
        /// </summary>
        public RelayCommand<bool> SelectAllMembersCommand
        {
            get
            {
                return _selectAllMembersCommand
                       ?? (_selectAllMembersCommand = new RelayCommand<bool>(
                           isChecked =>
                           {
                               if (isChecked)
                               {
                                   foreach (var member in _memberList)
                                   {
                                       member.IsMemberSelected = true;
                                   }
                               }
                               else
                               {
                                   foreach (var member in _memberList)
                                   {
                                       member.IsMemberSelected = false;
                                   }
                               }
                           }));
            }
        }

        /// <summary>
        ///     Gets the MyCommand.
        /// </summary>
        public RelayCommand<bool> SelectAllMembersCommandTwo
        {
            get
            {
                return _selectAllMembersCommandTwo
                       ?? (_selectAllMembersCommandTwo = new RelayCommand<bool>(
                           isChecked =>
                           {
                               if (isChecked)
                               {
                                   foreach (var member in _memberList)
                                   {
                                       member.IsMemberSelected = true;
                                   }
                               }
                               else
                               {
                                   foreach (var member in _memberList)
                                   {
                                       member.IsMemberSelected = false;
                                   }
                               }
                           }));
            }
        }

        /// <summary>
        ///     Sets and gets the CommentTypeHeading property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public static string CommentTypeHeading
        {
            get { return _commentTypeHeading; }

            set
            {
                if (_commentTypeHeading == value)
                {
                    return;
                }

                _commentTypeHeading = value;
                //RaisePropertyChanged(CommentTypeHeadingPropertyName);
            }
        }

        public MemberModel LoggedInMember { get; set; }

        /// <summary>
        ///     Gets the ClearCommand.
        /// </summary>
        public RelayCommand ClearCommand
        {
            get
            {
                return _clearCommand
                       ?? (_clearCommand = new RelayCommand(
                           Clear));
            }
        }

        public static event ScrollToAddedCommentDel ScrollToAddedCommentEvt;
        //Called by bottom app bar comment button click
        protected async void HandleMessages(NotificationMessage<MessageDataModel> mdm)
        {
            if (mdm.Notification.Equals(MessageCodes.SYNC_DATA_DOWNLOAD_SUCCESS))
            {
                GetMemberList();
            }

            if (mdm.Notification.Equals(MessageCodes.SYNC_UPDATED_DATA))
            {
                try
                {
                    var syncUpdatedData = (SyncUpdatedDataModel)mdm.Content.MessageData;
                    if (syncUpdatedData.Comments != null && syncUpdatedData.Comments.Count > 0)
                    {
                        if (syncUpdatedData.Comments.Any(item => item.Key.Equals(CommentType.ToString()) &&
                                                                 item.Value.Equals(TreeViewPageViewModel.MeetingId.ToString())))
                        {
                            await
                                CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                                    CoreDispatcherPriority.Normal, () => { GetCommentsList(RefId, CommentType); });
                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            if (mdm.Notification.Equals(MessageCodes.GET_COMMENTS))
            {
                try
                {
                    Comment = string.Empty;

                    if (CommentType.Equals(0))
                    {
                        RefId = AgendaItemId;
                        GetCommentsList(RefId, CommentType);
                    }
                    else
                    {
                        RefId = TreeViewPageViewModel.MeetingId;
                        GetCommentsList(RefId, CommentType);
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        public async void AddComments(string comment, List<int> userList)
        {
            comment = comment.Trim();
            try
            {
                //string commentWithMemberList = Comment + "#" + string.Join(",", userList);
                string commentWithMemberList;
                if (userList != null && userList.Count > 0) //Shared comment
                {
                    commentWithMemberList = Comment + ApplicationConstants.Seperator + string.Join(",", userList);
                    commentWithMemberList = commentWithMemberList + "," + Global.UserId;
                }
                else //Private comment
                {
                    commentWithMemberList = Comment + ApplicationConstants.Seperator + Global.UserId;
                }

                var result =
                    await
                        _commentService.AddComments(CommentType,
                            CommentType == 0
                                ? ApplicationConstants.LogActions.AddPaperComment
                                : ApplicationConstants.LogActions.AddMeetingComment,
                            commentWithMemberList, RefId, TreeViewPageViewModel.MeetingId);
                if (!result) return;

                var cm = new CommentModel
                {
                    MeetingId = TreeViewPageViewModel.MeetingId,
                    Comment = comment,
                    CommentByBackgroundColor = (CommentType == 1) ? "#1785ba" : "#6ac082",
                    CommentDate = DateTime.Now,
                    CommentDateString = Utility.GetDate(DateTime.Now).ToString(datetimeFormat),
                    CommentRightVisibility = Visibility.Visible,
                    CommentArrowPath = ImgPath + "Comment_MeetingCommentRightArrow.png",
                    CommentBackgroundColor = (CommentType == 1) ? "#f6fcff" : "#effff3",
                    CommentSyncedStatus = "Pending...",
                    CommentSyncingProgressVisibility = Visibility.Visible,
                    CommentBy = LoggedInMember.FullName,
                    //Email button will not be visible to pending comments
                    EmailBtnVisibility = Visibility.Collapsed
                };
                //CommentType = 0 -> paperComment / CommentType = 1 -> Meeting Comment
                
                CommentsList.Add(cm);
                if (ScrollToAddedCommentEvt != null) ScrollToAddedCommentEvt("New Comment Added");

                Clear();
            }
            catch (Exception)
            {
            }
        }

        public async void GetCommentsList(int refId, int commentType)
        {
            try
            {
                IEnumerable<CommentModel> allComments =
                    await _commentService.GetCommentTypeWiseComment(refId, commentType);
                CommentsList = new ObservableCollection<CommentModel>(allComments);

                foreach (var item in CommentsList)
                {
                    item.EmailBtnBgColor = "#01a4ef";
                    item.CommentByBackgroundColor = (CommentType == 1) ? "#1785ba" : "#6ac082";
                    
                    item.CommentDateString = Utility.GetDate(item.CommentDate).ToString(datetimeFormat);
                    //item.CommentDateString = item.CommentDateString + " " + item.CommentDate.ToString(datetimeFormat);
                    // 0 == paperComment | 1 == Meeting Comment
                    item.EmailBtnVisibility = item.PendingStatus == 1 ? Visibility.Collapsed : Visibility.Visible;
                    item.CommentSyncedStatus = item.PendingStatus == 1 ? "Pending..." : null;
                    
                    if (item.MemberId == Global.UserId)
                    {
                        item.CommentRightVisibility = Visibility.Visible;
                        item.CommentArrowPath = (CommentType == 1)
                            ? (ImgPath + "Comment_MeetingCommentRightArrow.png")
                            : (ImgPath + "Comment_PaperCommentRightArrow.png");
                        item.CommentBackgroundColor = (CommentType == 1) ? "#f6fcff" : "#effff3";
                    }

                    if (item.MemberId != Global.UserId)
                    {
                        item.CommentLeftVisibility = Visibility.Visible;
                        item.CommentArrowPath = (CommentType == 1)
                            ? (ImgPath + "Comment_MeetingCommentLeftArrow.png")
                            : (ImgPath + "Comment_PaperCommentleftArrow.png");
                        item.CommentBackgroundColor = (CommentType == 1) ? "#ebf9ff" : "#d8f5e0";
                    }
                }

                CommentListUpdatedNotification("CommentsList Updated");
            }
            catch (Exception)
            {
            }
        }

        public async void GetMemberList()
        {
            try
            {
                var meetingModel = await _meetingService.GetMeetingById(TreeViewPageViewModel.MeetingId);
                var memList = await _agendaService.GetParticipantsListForMeeting(meetingModel.MeetingId);

                //Remove logged user from member list
                LoggedInMember = memList.FirstOrDefault(m => m.MemberId == Global.UserId);
                memList.Remove(LoggedInMember);

                await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
                {
                    foreach (var item in memList)
                    {
                        item.ProfilePicPath = await BasePage.UpdateProfilePic(item.MemberId);
                    }
                });

                MemberList = new ObservableCollection<MemberModel>(memList);
            }
            catch (Exception)
            {
            }
        }

        public void Clear()
        {
            try
            {
                var mList = MemberList.Where(m => m.IsMemberSelected.Equals(true)).ToList();
                foreach (var item in mList)
                {
                    item.IsMemberSelected = false;
                }

                Comment = string.Empty;
            }
            catch (Exception)
            {
            }
        }

        #region Auto scroll comments list when new comment added. called to AddCommentsPage.xaml.cs method(private async void ScrollToItem(string obj))

        private static Action<string> _newCommentAddedCallback;

        public static void SubscribeToNewlyAddedComment<T>(Action<string> callback)
        {
            _newCommentAddedCallback = callback;
        }

        private void CommentListUpdatedNotification(string data)
        {
            if (_newCommentAddedCallback != null)
                _newCommentAddedCallback.BeginInvoke(data, null, null);
        }

        #endregion
    }

    public class IntToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            var commentCount = (int)value;
            if (commentCount > 99)
            {
                return "99+";
            }

            return commentCount;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}